home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / 4_0 / 3D_GRAPH / GRAPH3D.C < prev    next >
C/C++ Source or Header  |  1990-01-04  |  36KB  |  2,067 lines

  1. /*
  2.     Copyright '89    Christopher Moll
  3.     all rights reserved
  4. */
  5.  
  6.  
  7. #include    "graph3D.h"
  8. #include <ColorToolbox.h>
  9.  
  10. #include <math.h>
  11. #ifndef    _LSC3_
  12. #    include <MemoryMgr.h>
  13. #    include <FileMgr.h>
  14. #    include <WindowMgr.h>
  15. #    include <DialogMgr.h>
  16. #    include <EventMgr.h>
  17. #    include <TextEdit.h>
  18. #    include <DeskMgr.h>
  19. #    include <MenuMgr.h>
  20. #    include <ScrapMgr.h>
  21. #endif
  22.  
  23.  
  24. extern    Real    startR, startT;
  25. extern    Real    endR, endT;
  26. extern    Real    deltaR, deltaT;
  27. extern    int        numR, numT;
  28.  
  29. extern    Real    startX, startY;
  30. extern    Real    endX, endY;
  31. extern    Real    deltaX, deltaY;
  32. extern    int        numX, numY;
  33.  
  34. extern    WindowRecord    gwindRecord;
  35.  
  36. extern    Uchar        *gridFace;
  37.  
  38.  
  39.  
  40. /* windows */
  41. GrafPtr            windManPort;
  42.  
  43. WindowPtr        graphWind;
  44.  
  45.  
  46. /* Dialogs */
  47. DialogRecord    sdialRecord;    /* storage for the dialog */
  48. DialogPtr        specDial;
  49. Boolean            specDOpen = FALSE;
  50. DialogRecord    lmdialRecord;    /* storage for the dialog */
  51. DialogPtr        limtDial;
  52. Boolean            limtDOpen = FALSE;
  53. DialogRecord    funcDialRecord;    /* storage for the dialog */
  54. DialogPtr        functDial;
  55. Boolean            functDOpen = FALSE;
  56.  
  57.  
  58. /* menus */
  59. MenuHandle        appleMenu, fileMenu, editMenu, plotMenu,
  60.                 gTypeMenu, windwMenu;
  61.  
  62.  
  63. /* Clipboard stuff */
  64. int            scrapCompare;    /* status of the deskscrap (clipboard) */
  65. Boolean        scrapDirty;        /* deskscrap has been changed */
  66. Boolean        isScrapTE;        /* there's text in the deskscrap */
  67. Boolean        isScrapPIC;        /* there's a picture in the deskscrap */
  68.  
  69. Boolean        appActive = TRUE;
  70.  
  71.  
  72. Boolean        useMainFunc;
  73.  
  74. int        mainFunct[64];
  75. int        numMnOps;
  76. Real    mnConsts[30];
  77. int        numMnConsts = 0;
  78.  
  79. int        derivFunct[64];
  80. int        numDerivOps;
  81. Real    derivConsts[30];
  82. int        numDerivConsts = 0;
  83.  
  84.  
  85. /* graph points in various forms */
  86. Real        *funcResults = NIL;        /* changes when function changed,
  87.                                         new file opened, etc. */
  88. Vector        *scalVectResults = NIL;        /* changes when function changed,
  89.                                         new file opened, etc. */
  90. Point        *graphPoints = NIL;        /* changes when rotation changes */
  91.  
  92. Vector        maxVect, minVect;
  93.  
  94. Point    XaxisPt, YaxisPt, ZaxisPt;
  95. Point    Origin = {0, 0};
  96. Rect    graphRect = {40, 40, 300, 470};
  97.  
  98.  
  99.  
  100. Real    rotMatrx[3][3];
  101.  
  102. Real    scale;
  103.  
  104.  
  105. Boolean        functCurrent = FALSE;    /* function evaluated and stored in funcResults*/
  106. Boolean        specsCurrent = FALSE;    /* funtion evaluated according to current specification
  107.                                         dialog contents ('begin', 'end').
  108.                                                     If not , reevaluate function */
  109. Boolean        vectrsCurrent = FALSE;    /* vectors have been set from the function */
  110. Boolean        pntsCurrent = FALSE;    /* pnts have been taken from the vectors and scaled
  111.                                         to fit in window */
  112.  
  113. Boolean        noRedrawGrph = FALSE;    /* graph being worked on;
  114.                                     don't try to redraw it */
  115.  
  116. Boolean        hideSurface = FALSE, useHeight = FALSE;
  117. Boolean        xAxPos, yAxPos;
  118. int            graphType = FUNCT_GTYPE;
  119.  
  120.  
  121. Real    zScale = 1.0;
  122. Real    ceilgZ = 1e100, floorZ = -1e100;
  123.  
  124. Real    cosSrc = .86602540378444, sinSrc = .5;    /* 30 degrees */
  125.  
  126.  
  127. Boolean        colorQD, scrnColor, colorNorms;
  128. Boolean        grphOnScrn = FALSE;
  129.  
  130. PatternList        *greyList;
  131.  
  132.  
  133. EventRecord        theEvent;
  134. Boolean            inMultiFndr;
  135. long            sleepPeriod = 2;
  136.  
  137. long        startRedraw = -1;
  138.  
  139. long    MoveToAddr, LineToAddr, FixMulAddr;
  140.  
  141.  
  142.  
  143. main()
  144. {
  145.     DoSetup();
  146.     SelectWindow(graphWind);
  147.  
  148.     while (1)
  149.     {
  150.         DialogIdle();
  151.         if (inMultiFndr)
  152.         {
  153.             if (WaitNextEvent(everyEvent, &theEvent, sleepPeriod, NIL))
  154.             {
  155.                 DoEvent();
  156.                 InitCursor();
  157.             }
  158.         }
  159.         else
  160.         {
  161.             if (GetNextEvent(everyEvent, &theEvent))
  162.             {
  163.                 DoEvent();
  164.                 InitCursor();
  165.             }
  166.             SystemTask();
  167.         }
  168.     }
  169. }
  170.  
  171. static
  172. DialogIdle()
  173. {
  174.     WindowPtr    frontW;
  175.  
  176.     frontW = FrontWindow();
  177.  
  178.     if (frontW EQ functDial)
  179.         TEIdle(funcDialRecord.textH);
  180.     else if (frontW EQ specDial)
  181.         TEIdle(sdialRecord.textH);
  182.     else if (frontW EQ limtDial)
  183.         TEIdle(lmdialRecord.textH);
  184. }
  185.  
  186. DoEvent()
  187. {
  188.     DialogPtr    theDial;
  189.     int            theItem;
  190.     Boolean        result, ScrnHasColor();
  191.  
  192.     scrnColor = ScrnHasColor();    /* check current screen status */
  193.  
  194.     if (theEvent.what EQ resumEvt)
  195.         DoSuspndRsm(theEvent.message);
  196.     
  197.     if (IsDialogEvent(&theEvent))
  198.         DoDialogEvent();
  199.     else
  200.     {
  201.         switch (theEvent.what) {
  202.         case nullEvent:
  203.             break;
  204.         case mouseDown:
  205.             DoMouseDown();
  206.             break;
  207.         case mouseUp:
  208.             break;
  209.         case keyDown:
  210.         case autoKey:
  211.             DoKeyDown();
  212.             break;
  213.         case updateEvt:
  214.             DoUpdate();
  215.             break;
  216.         case diskEvt:
  217.             break;
  218.         case activateEvt:
  219.             DoActivate();
  220.             break;
  221.         case networkEvt:
  222.         case driverEvt:
  223.             break;
  224.         }
  225.     }
  226. }
  227.  
  228. static
  229. DoDialogEvent()
  230. {
  231.     DialogPtr    theDial;
  232.     int            theItem;
  233.     Boolean        ChkCmndKey(), ChkNmbrKey();
  234.  
  235.     theDial = FrontWindow();
  236.  
  237.     if ((theEvent.what EQ keyDown) OR (theEvent.what EQ autoKey))
  238.     {
  239.         if (ChkCmndKey(theDial))
  240.             return;
  241.         if ((theDial EQ specDial) OR (theDial EQ limtDial))
  242.         {
  243.             if (NOT(ChkNmbrKey()))
  244.                 return;
  245.         }
  246.         else
  247.             functCurrent = FALSE;
  248.     }
  249.  
  250.     if (theEvent.what EQ activateEvt)    /* if it's a DA, get or write clip */
  251.     {
  252.         if (theEvent.modifiers & activeFlag)
  253.             ReadDeskScrap();
  254.         else
  255.             WriteDeskScrap();
  256.     }
  257.  
  258.     DialogSelect(&theEvent, &theDial, &theItem);
  259.     if (theItem EQ DIALI_S_REDRWB)
  260.         DoRedraw();
  261. }
  262.  
  263. /*** Force an update of the graph ***/
  264. InvalidGraph()
  265. {
  266.     GrafPtr    savePort;
  267.  
  268.     GetPort(&savePort);
  269.     SetPort(graphWind);
  270.         InvalRect(&graphWind->portRect);
  271.     SetPort(savePort);
  272. }
  273.  
  274. /*** Called when a modeless dialog is frontmost; checks for and
  275.         deals with command keys ***/
  276. static
  277. Boolean
  278. ChkCmndKey(theDial)
  279. DialogPtr    theDial;
  280. {
  281.     if (theEvent.modifiers & cmdKey)
  282.     {
  283.         DoKeyDown();
  284.         return(TRUE);
  285.     }
  286.  
  287.     return(FALSE);
  288. }
  289.  
  290. static
  291. Boolean
  292. ChkNmbrKey()
  293. {
  294.     char    typed;
  295.  
  296.     typed = (char)(theEvent.message & charCodeMask);
  297.  
  298.     if (IS_DIGIT(typed))
  299.         return(TRUE);
  300.  
  301.     switch (typed)
  302.     {
  303.     case '-':
  304.     case '.':
  305.     case 'e':
  306.     case '\t':
  307.     case '\b':
  308.         return(TRUE);
  309.     }
  310.  
  311.     return(FALSE);
  312. }
  313.  
  314. static
  315. DoMouseDown()
  316. {
  317.     int thePart;
  318.     WindowPtr whichWindow;
  319.  
  320.     thePart = FindWindow( theEvent.where, &whichWindow);
  321.  
  322.     switch (thePart) {
  323.     case inDesk:
  324.         break;
  325.     case inMenuBar:
  326.         DoMenuClick();
  327.         break;
  328.     case inSysWindow:
  329.         SystemClick(&theEvent, whichWindow);
  330.         break;
  331.     case inContent:
  332.         DoContent(whichWindow);
  333.         break;
  334.     case inDrag:
  335.         DoDrag(whichWindow);
  336.         break;
  337.     case inGrow:
  338.         DoGrow(whichWindow);
  339.         break;
  340.     case inGoAway:
  341.         DoGoAway(whichWindow, TRUE);
  342.         break;
  343.     case inZoomIn:
  344.     case inZoomOut:
  345.         DoZoom(whichWindow, thePart);
  346.         break;
  347.     }
  348. }
  349.  
  350. static
  351. DoMenuClick()
  352. {
  353.     long menuChoice;
  354.  
  355.     menuChoice = MenuSelect(theEvent.where);
  356.     DoMenuChoice(menuChoice);
  357. }
  358.  
  359. static
  360. DoMenuChoice(menuChoice)
  361. long menuChoice;
  362. {
  363.     Clock();
  364.     switch(HiWord(menuChoice)) {
  365.     case MENU_APPLE:
  366.         DoAppleChoice( LoWord(menuChoice) );
  367.         break;
  368.     case MENU_FILE:
  369.         DoFileMenu(LoWord(menuChoice));
  370.         break;
  371.     case MENU_EDIT:
  372.         DoEditMenu(LoWord(menuChoice));
  373.         break;
  374.     case MENU_PLOT:
  375.         DoPlotMenu(LoWord(menuChoice));
  376.         break;
  377.     case MENU_GTYP:
  378.         DoGTypeMenu(LoWord(menuChoice));
  379.         break;
  380.     case MENU_WIND:
  381.         DoWindwMenu(LoWord(menuChoice));
  382.         break;
  383.     }
  384.  
  385.     HiliteMenu(0); /* unhilight the selected menu */
  386. }
  387.  
  388. static
  389. DoAppleChoice(theItem)
  390. int theItem;
  391. {
  392.     char    accName[256];
  393.     int        accNum, i;
  394.  
  395.     WriteDeskScrap();
  396.  
  397.     if (theItem EQ 1)
  398.         DoAbout();
  399.     else
  400.     {
  401.         GetItem(appleMenu, theItem, accName);
  402.         accNum = OpenDeskAcc(accName);
  403.     }
  404. }
  405.  
  406. static
  407. DoAbout()
  408. {
  409.     InitCursor();
  410.     Alert(ALRT_ABOUT, NIL);
  411. }
  412.  
  413. static
  414. DoFileMenu(theItem)
  415. int theItem;
  416. {
  417.     Boolean        ReadData();
  418.  
  419.     switch(theItem) {
  420.     case FILE_OPEN:
  421.         if (graphType NEQ FDATA_GTYPE)
  422.             DoGTypeMenu(FDATA_GTYPE);    /* "Data File" from gtype menu */
  423.         else
  424.         {
  425.             if (ReadData())
  426.                 InvalidGraph();
  427.         }
  428.         break;
  429.     case FILE_OPEN_MAND:
  430.         OpenMandel();
  431.         break;
  432.     case FILE_CLOSE:
  433.         DoGoAway(FrontWindow(), FALSE);
  434.         break;
  435.     case FILE_SVBITM:
  436.         SavePICT(FALSE);
  437.         break;
  438.     case FILE_SVOBJ:
  439.         SavePICT(TRUE);
  440.         break;
  441.     case FILE_QUIT:
  442.         DoQuit();
  443.         break;
  444.     }
  445. }
  446.  
  447. static
  448. DoQuit()
  449. {
  450.     CloseWindow(graphWind);
  451.     if (scrnColor)
  452.         GetNewCWindow(130, &gwindRecord, -1L);
  453.     exit();
  454. }
  455.  
  456. static
  457. DoEditMenu(theItem)
  458. int theItem;
  459. {
  460.     WindowPtr    frontW;
  461.     frontW = FrontWindow();
  462.  
  463.     switch(theItem) {
  464.     case 1: /* Undo */
  465.         SystemEdit(undoCmd);
  466.         break;
  467.     case 3: /* Cut */
  468.         if (NOT(SystemEdit(cutCmd)))
  469.             DoCut(frontW);
  470.         break;
  471.     case 4: /* Copy */
  472.         if (NOT(SystemEdit(copyCmd)))
  473.             DoCopy(frontW);
  474.         break;
  475.     case 5: /* Paste */
  476.         if (NOT(SystemEdit(pasteCmd)))
  477.             DoPaste(frontW);
  478.         break;
  479.     case 6: /* Clear */
  480.         if (NOT(SystemEdit(clearCmd)))
  481.             DoClear(frontW);
  482.         break;
  483.     }
  484. }
  485.  
  486. static
  487. DoCut(frontW)
  488. WindowPtr    frontW;
  489. {
  490.     Boolean        IsDialog();
  491.     
  492.     if (IsDialog(frontW))
  493.     {
  494.         DlgCut(frontW);
  495.         scrapDirty = TRUE;
  496.     }
  497. }
  498.  
  499. static
  500. DoCopy(frontW)
  501. WindowPtr    frontW;
  502. {
  503.     Boolean        IsDialog();
  504.     
  505.     if (IsDialog(frontW))
  506.         DlgCopy(frontW);
  507.     else if (frontW EQ graphWind)
  508.         CopyGraph();
  509.     scrapDirty = TRUE;
  510. }
  511.  
  512. static
  513. CopyGraph()
  514. {
  515.     PicHandle    GetGraphPICT();
  516.     PicHandle    graphPict;
  517.  
  518.     graphPict = GetGraphPICT(OptionDown());
  519.     if (NOT(graphPict))
  520.         return;
  521.  
  522.     ZeroScrap();
  523.     PutScrap(GetHandleSize(graphPict), 'PICT', *graphPict);
  524.     isScrapPIC = TRUE;
  525.     isScrapTE = FALSE;
  526. }
  527.  
  528. static
  529. DoPaste(frontW)
  530. WindowPtr    frontW;
  531. {
  532.     Boolean        IsDialog();
  533.     
  534.     if (IsDialog(frontW))
  535.         DlgPaste(frontW);
  536. }
  537.  
  538. static
  539. DoClear(frontW)
  540. WindowPtr    frontW;
  541. {
  542.     Boolean        IsDialog();
  543.     
  544.     if (IsDialog(frontW))
  545.         DlgDelete(frontW);
  546. }
  547.  
  548. static
  549. Boolean
  550. IsDialog(theWind)
  551. WindowPtr    theWind;
  552. {
  553.     return
  554.             ((theWind EQ specDial) OR 
  555.             (theWind EQ limtDial) OR 
  556.             (theWind EQ functDial));
  557. }
  558.  
  559. static
  560. DoPlotMenu(theItem)
  561. int theItem;
  562. {
  563.     switch(theItem) {
  564.     case PLOT_WIREFRAM: /* just lines */
  565.         hideSurface = FALSE;
  566.         useHeight = FALSE;
  567.         CheckItem(plotMenu, PLOT_WIREFRAM, TRUE);
  568.         CheckItem(plotMenu, PLOT_SHDSURF, FALSE);
  569.         CheckItem(plotMenu, PLOT_SHDHITE, FALSE);
  570.         InvalidGraph();
  571.         break;
  572.     case PLOT_SHDSURF: /* Hide surfaces */
  573.         CheckItem(plotMenu, PLOT_WIREFRAM, FALSE);
  574.         if (useHeight)    /* hideSurface TRUE */
  575.         {
  576.             useHeight = FALSE;
  577.             pntsCurrent = FALSE;
  578.             CheckItem(plotMenu, PLOT_SHDSURF, TRUE);
  579.             CheckItem(plotMenu, PLOT_SHDHITE, FALSE);
  580.             CheckHideView();
  581.             InvalidGraph();
  582.         }
  583.         else if (NOT(hideSurface))
  584.         {
  585.             hideSurface = TRUE;
  586.             useHeight = FALSE;
  587.             pntsCurrent = FALSE;
  588.             CheckItem(plotMenu, PLOT_SHDSURF, TRUE);
  589.             CheckHideView();
  590.             InvalidGraph();
  591.         }
  592.         break;
  593.     case PLOT_SHDHITE: /* Shade by hight */
  594.         CheckItem(plotMenu, PLOT_WIREFRAM, FALSE);
  595.         if (NOT(useHeight))
  596.         {
  597.             hideSurface = TRUE;
  598.             useHeight = TRUE;
  599.             pntsCurrent = FALSE;
  600.             CheckItem(plotMenu, PLOT_SHDSURF, FALSE);
  601.             CheckItem(plotMenu, PLOT_SHDHITE, TRUE);
  602.             CheckHideView();
  603.             InvalidGraph();
  604.         }
  605.         break;
  606.     case PLOT_SETLITE: /* Set light source */
  607.         SetLightSrc();
  608.         break;
  609.     case PLOT_ZEROROT: /* Zero Rotation */
  610.         MkIDMat(rotMatrx);
  611.         vectrsCurrent = FALSE;
  612.         InvalidGraph();
  613.         break;
  614.     case PLOT_NORMVIEW: /* Normal View */
  615.         MkRotMat(0.0, -.3, -.3, rotMatrx);
  616.         vectrsCurrent = FALSE;
  617.         InvalidGraph();
  618.         break;
  619.     case PLOT_TOPVIEW: /* Top View */
  620.         MkRotMat(0.0, PI/2.0, 0.0, rotMatrx);
  621.         vectrsCurrent = FALSE;
  622.         InvalidGraph();
  623.         break;
  624.     case PLOT_REDRAW: /* ReDraw */
  625.         DoRedraw();
  626.         break;
  627.     }
  628. }
  629.  
  630. CheckHideView()
  631. {
  632.     Vector        testVect, resVect;
  633.  
  634.     testVect.x = 1;
  635.     testVect.y = 0;
  636.     testVect.z = 0;
  637.     MatrxMul(rotMatrx, &testVect, &resVect);
  638.  
  639.     xAxPos = (resVect.x > 0);
  640.     testVect.x = 0;
  641.     testVect.y = 1;
  642.     MatrxMul(rotMatrx, &testVect, &resVect);
  643.     yAxPos = (resVect.x > 0);
  644. }
  645.  
  646. static
  647. SetLightSrc()
  648. {
  649.     Point    center, chosen;
  650.     EventRecord    msEvent;
  651.     Real    horiz, vert, len;
  652.  
  653.     InitCursor();
  654.     SelectWindow(graphWind);
  655.     center.h = (graphWind->portRect.right - graphWind->portRect.left) >> 1;
  656.     center.v = (graphWind->portRect.bottom - graphWind->portRect.top) >> 1;
  657.  
  658.     while (!GetNextEvent(mDownMask, &msEvent));
  659.     chosen = msEvent.where;
  660.     GlobalToLocal(&chosen);
  661.  
  662.     horiz = chosen.h - ((graphWind->portRect.right - graphWind->portRect.left) >> 1);
  663.     vert = chosen.v - ((graphWind->portRect.bottom - graphWind->portRect.top) >> 1);
  664.     len = SQ(horiz) + SQ(vert);
  665.     len = -sqrt(len);
  666.     sinSrc = horiz / len;
  667.     cosSrc = vert / len;
  668.  
  669.     if (hideSurface AND NOT(useHeight))
  670.         InvalidGraph();
  671.     pntsCurrent = FALSE;
  672. }
  673.  
  674. static
  675. DoRedraw()
  676. {
  677.     GetLimtDCont();
  678.  
  679.     startRedraw = Ticks;
  680.  
  681.     if (graphType NEQ FDATA_GTYPE)
  682.     {
  683.         GetSpecDCont();
  684.         if (NOT(specsCurrent AND functCurrent))
  685.             if ((graphType EQ FUNCT_GTYPE) OR (graphType EQ DERIV_GTYPE))
  686.                 EvalFunction();
  687.             else
  688.                 EvalCylindFunct();
  689.     }
  690.     
  691.     InvalidGraph();
  692. }
  693.  
  694. DoGTypeMenu(theItem)
  695. int theItem;
  696. {
  697. Rect    fWindRect;
  698.  
  699.     switch(theItem) {
  700.     case FUNCT_GTYPE: /* Function */
  701.         SetToFunction();
  702.         break;
  703.     case CYLIND_GTYPE: /* Cylindrical */
  704.         SetToCylind();
  705.         break;
  706.     case DERIV_GTYPE: /* Derivative */
  707.         SetToDeriv();
  708.         break;
  709.     case FDATA_GTYPE: /* File Data */
  710.         SetToDataFile();
  711.         break;
  712.     }
  713. }
  714.  
  715. static
  716. SetToFunction()
  717. {
  718.     if (graphType NEQ FUNCT_GTYPE)
  719.     {
  720.         CheckItem(gTypeMenu, graphType, FALSE);
  721.         SetFunctDialType(FUNCT_GTYPE);
  722.         CheckItem(gTypeMenu, graphType, TRUE);
  723.     }
  724. }
  725.  
  726. static
  727. SetToCylind()
  728. {
  729.     if (graphType NEQ CYLIND_GTYPE)
  730.     {
  731.         CheckItem(gTypeMenu, graphType, FALSE);
  732.         SetFunctDialType(CYLIND_GTYPE);
  733.         CheckItem(gTypeMenu, graphType, TRUE);
  734.     }
  735. }
  736.  
  737. static
  738. SetToDeriv()
  739. {
  740.     if (graphType NEQ DERIV_GTYPE)
  741.     {
  742.         CheckItem(gTypeMenu, graphType, FALSE);
  743.         SetFunctDialType(DERIV_GTYPE);
  744.         CheckItem(gTypeMenu, graphType, TRUE);
  745.     }
  746. }
  747.  
  748. ARD(a)
  749. register int a;
  750. {
  751.     DeBug();
  752. }
  753.  
  754. static
  755. SetToDataFile()
  756. {
  757.     Boolean        ReadData();
  758.  
  759.     if (graphType NEQ FDATA_GTYPE)
  760.         if (ReadData())
  761.         {
  762.             CheckItem(gTypeMenu, graphType, FALSE);
  763.             SetFunctDialType(FDATA_GTYPE);
  764.             CheckItem(gTypeMenu, graphType, TRUE);
  765.             InvalidGraph();
  766.         }
  767. }
  768.  
  769. static
  770. SetFunctDialType(newType)
  771. int    newType;
  772. {
  773.     int    oldType;
  774.     
  775.     oldType = graphType;
  776.     graphType = newType;
  777.  
  778.     CloseSpecDial();
  779.     ShowSpecs();
  780.  
  781.     if (newType EQ FDATA_GTYPE)
  782.     {
  783.         if ((oldType EQ FUNCT_GTYPE) OR (oldType EQ DERIV_GTYPE))
  784.             CloseFunctDial();
  785.     }
  786.     else
  787.     {
  788.         CloseFunctDial();
  789.         ShowFunctDial();
  790.     }
  791. }
  792.  
  793. static
  794. CloseSpecDial()
  795. {
  796.     if (specDOpen)
  797.     {
  798.         CloseDialog(specDial);
  799.         specDOpen = FALSE;
  800.     }
  801. }
  802.  
  803. static
  804. DoWindwMenu(theItem)
  805. int theItem;
  806. {
  807.     switch    (theItem)
  808.     {
  809.     case WINDMEN_GRAPH: /* Show graph */
  810.         SelectWindow(graphWind);
  811.         break;
  812.     case WINDMEN_FUNCT: /* Show function */
  813.         ShowFunctDial();
  814.         break;
  815.     case WINDMEN_SPECS: /* Show Plot Specs*/
  816.         ShowSpecs();
  817.         break;
  818.     case WINDMEN_LIMITS: /* Show Limits */
  819.         ShowLimits();
  820.         break;
  821.     }
  822. }
  823.  
  824. static
  825. DoContent(whichWindow)
  826. WindowPtr whichWindow;
  827. {
  828.     if (whichWindow NEQ FrontWindow())
  829.         SelectWindow(whichWindow);
  830.     else if (FrontWindow() EQ graphWind)
  831.         ClikRot();
  832. }
  833.  
  834. Rect    hndRct[5], vertRect, horizRect, centrRect;
  835. Point    drawWCntr;
  836.  
  837. static
  838. ClikRot()
  839. {
  840.     Real    newRot[3][3], temp[3][3];
  841.     Real    rot;
  842.     Point    msDLoc;
  843.     int        quad;
  844.     int        WhatQuad();
  845.     int        XArcShow(), PYArcShow(), NZArcShow(), PZArcShow(), NYArcShow();
  846.  
  847.     msDLoc = theEvent.where;
  848.     GlobalToLocal(&msDLoc);
  849.     quad = WhatQuad(&msDLoc);
  850.     if (quad EQ -1)
  851.         return;
  852.  
  853.     switch (quad)
  854.     {
  855.     case 0:
  856.         rot = -DEGtoRAD * NYArcShow(&vertRect);
  857.         MkYRotMat(rot, newRot);
  858.         if (rot NEQ 0.0)
  859.             SRotatePoints(cos(rot), sin(rot), 2);
  860.         break;
  861.     case 3:
  862.         rot = -DEGtoRAD * NZArcShow(&horizRect);
  863.         MkZRotMat(rot, newRot);
  864.         if (rot NEQ 0.0)
  865.             SRotatePoints(cos(rot), sin(rot), 3);
  866.         break;
  867.     case 1:
  868.         rot = DEGtoRAD * PYArcShow(&vertRect);
  869.         MkYRotMat(rot, newRot);
  870.         if (rot NEQ 0.0)
  871.             SRotatePoints(cos(rot), sin(rot), 2);
  872.         break;
  873.     case 2:
  874.         rot = DEGtoRAD * PZArcShow(&horizRect);
  875.         MkZRotMat(rot, newRot);
  876.         if (rot NEQ 0.0)
  877.             SRotatePoints(cos(rot), sin(rot), 3);
  878.         break;
  879.     case 4:
  880.         rot = DEGtoRAD * XArcShow(¢rRect);
  881.         MkXRotMat(rot, newRot);
  882.         if (rot NEQ 0.0)
  883.             SRotatePoints(cos(rot), sin(rot), 4);
  884.         break;
  885.     }
  886.     pntsCurrent = FALSE;
  887.  
  888.     MatrxByMatrx(newRot, rotMatrx, temp);
  889.     CopyMat(temp, rotMatrx);
  890.  
  891.     InvalidGraph();
  892. }
  893.  
  894. static
  895. DoDrag(whichWindow)
  896. WindowPtr whichWindow;
  897. {
  898.     Rect limitRect;
  899.  
  900.     SetRect(&limitRect, 0, 0, 2000, 2000);
  901.     DragWindow(whichWindow, theEvent.where, &limitRect);
  902. }
  903.  
  904. DoGrow(whichWindow)
  905. WindowPtr whichWindow;
  906. {
  907.     Rect limitRect;
  908.     long    newSize;
  909.  
  910.     if (whichWindow EQ graphWind)
  911.     {
  912.         SetRect(&limitRect, 50, 50, 2000, 2000);
  913.         newSize = GrowWindow(whichWindow, theEvent.where, &limitRect);
  914.         if (newSize)
  915.         {
  916.             SizeWindow(whichWindow, LoWord(newSize), HiWord(newSize), TRUE);
  917.             if (whichWindow EQ graphWind)
  918.             {
  919.                 SetGraphRect();
  920.                 vectrsCurrent = FALSE;
  921.                 InvalidGraph();
  922.             }
  923.         }
  924.     }
  925. }
  926.  
  927. SetGraphRect()
  928. {
  929.     graphRect = graphWind->portRect;
  930.     InsetRect(&graphRect, 2, 2);
  931.     SetRotateHandles();
  932. }
  933.  
  934. static
  935. DoGoAway(whichWindow, needTrack)
  936. WindowPtr    whichWindow;
  937. Boolean        needTrack;
  938. {
  939.     if (needTrack)
  940.         if (NOT(TrackGoAway(whichWindow, theEvent.where)))
  941.             return;
  942.     if (whichWindow EQ graphWind)
  943.         exit();
  944.     else if (whichWindow EQ functDial)
  945.         CloseFunctDial();
  946.     else if (whichWindow EQ specDial)
  947.         CloseSpecDial();
  948.     else if (whichWindow EQ limtDial)
  949.     {
  950.         GetLimtDCont();
  951.         CloseDialog(limtDial);
  952.         limtDOpen = FALSE;
  953.     }
  954. }
  955.  
  956. static
  957. CloseFunctDial()
  958. {
  959.     if (functDOpen)
  960.     {
  961.         CloseDialog(functDial);
  962.         functDOpen = FALSE;
  963.     }
  964. }
  965.  
  966. GetSpecDCont()
  967. {
  968.     Real    temp;
  969.     Real    DialogField();
  970.  
  971.     if (NOT(specDOpen))
  972.         return;
  973.  
  974.     temp = DialogField(specDial, DIALI_S_SX);
  975.     specsCurrent = startX EQ temp;
  976.     startX = temp;
  977.  
  978.     temp = DialogField(specDial, DIALI_S_EX);
  979.     specsCurrent = specsCurrent AND (endX EQ temp);
  980.     endX = temp;
  981.  
  982.     temp = DialogField(specDial, DIALI_S_SY);
  983.     specsCurrent = specsCurrent AND (startY EQ temp);
  984.     startY = temp;
  985.  
  986.     temp = DialogField(specDial, DIALI_S_EY);
  987.     specsCurrent = specsCurrent AND (endY EQ temp);
  988.     endY = temp;
  989.  
  990.     temp = (int)DialogField(specDial, 14);
  991.     if ((numX-1) NEQ temp)
  992.     {
  993.         specsCurrent = FALSE;
  994.         numX = temp;
  995.         ++numX;
  996.     }
  997.  
  998.     temp = (int)DialogField(specDial, 15);
  999.     if ((numY-1) NEQ temp)
  1000.     {
  1001.         specsCurrent = FALSE;
  1002.         numY = temp;
  1003.         ++numY;
  1004.     }
  1005.     if (graphType EQ CYLIND_GTYPE)
  1006.     {
  1007.         startR = startX;
  1008.         endR = endX;
  1009.         numR = numX;
  1010.         startT = startY * DEGtoRAD;
  1011.         endT = endY * DEGtoRAD;
  1012.         numT = numY;
  1013.     }
  1014. }
  1015.  
  1016. static
  1017. Real
  1018. DialogField(theDialog, theItem)
  1019. DialogPtr    theDialog;
  1020. int    theItem;
  1021. {
  1022.     int        itemType;
  1023.     Handle    itemHndle;
  1024.     Rect    itemRect;
  1025.     char    contStr[256];
  1026.     Real    atof(), res;
  1027.  
  1028.     GetDItem(theDialog, theItem, &itemType, &itemHndle, &itemRect);
  1029.     GetIText(itemHndle, contStr);
  1030.  
  1031.     ptoc(contStr);
  1032.     res = atof(contStr);
  1033.     return(res);
  1034. }
  1035.  
  1036. GetLimtDCont()
  1037. {
  1038.     Real    temp;
  1039.     Real    DialogField();
  1040.  
  1041.     if (NOT(limtDOpen))
  1042.         return;
  1043.  
  1044.     temp = DialogField(limtDial, DIALI_L_ZS);
  1045.     vectrsCurrent = zScale EQ temp;
  1046.     zScale = temp;
  1047.  
  1048.     temp = DialogField(limtDial, DIALI_L_C);
  1049.     vectrsCurrent = vectrsCurrent AND (ceilgZ EQ temp);
  1050.     ceilgZ = temp;
  1051.  
  1052.     temp = DialogField(limtDial, DIALI_L_F);
  1053.     vectrsCurrent = vectrsCurrent AND (floorZ EQ temp);
  1054.     floorZ = temp;
  1055. }
  1056.  
  1057. /***  zoom box clicked  ***/
  1058. static
  1059. DoZoom(whichWindow, thePart)
  1060. WindowPtr    whichWindow;
  1061. int            thePart;
  1062. {
  1063.     if (TrackBox(whichWindow, theEvent.where, thePart))    /* ROM */
  1064.     {
  1065.         ZoomWindow(whichWindow, thePart, TRUE);    /* ROM */
  1066.         if (whichWindow EQ graphWind)
  1067.         {
  1068.             SetGraphRect();
  1069.             vectrsCurrent = FALSE;
  1070.         }
  1071.     }
  1072. }
  1073.  
  1074. static
  1075. DoKeyDown()
  1076. {
  1077.     unsigned    char typed;
  1078.     long menuChoice;
  1079.  
  1080.     typed = theEvent.message & charCodeMask;
  1081.  
  1082.     if ((theEvent.modifiers & cmdKey)
  1083.         AND (theEvent.what NEQ autoKey)) /* ignore repeats */
  1084.     {
  1085.         menuChoice = MenuKey(typed);
  1086.         if (menuChoice)
  1087.             DoMenuChoice(menuChoice);
  1088.     }
  1089. }
  1090.  
  1091. static
  1092. DoUpdate()
  1093. {
  1094.     GrafPtr savePort;        /* to save and restore the old port */
  1095.     WindowPtr whichWindow;
  1096.  
  1097.     Clock();
  1098.     whichWindow = (WindowPtr) (theEvent.message);
  1099.  
  1100.     BeginUpdate(whichWindow);    /* reset ClipRgn etc to only redraw what's
  1101.                                necessary. */
  1102.  
  1103.         GetPort(&savePort);        /* don't trash the port; we might be
  1104.                                    updating an inactive window */
  1105.         SetPort(whichWindow);    /* work in the specified window */
  1106.  
  1107.         DrawWindow(whichWindow);
  1108.  
  1109.     EndUpdate(whichWindow);
  1110.  
  1111.     SetPort(savePort);
  1112. }
  1113.  
  1114. static
  1115. DrawWindow(whichWindow)
  1116. WindowPtr whichWindow;
  1117. {
  1118.     if (whichWindow EQ graphWind)
  1119.         UpdatGraphWind();
  1120. }
  1121.  
  1122. static
  1123. UpdatGraphWind()
  1124. {
  1125.     ClipRect(&graphWind->portRect);
  1126.  
  1127.     if (noRedrawGrph)
  1128.         return;
  1129.  
  1130.     if (NOT(vectrsCurrent))
  1131.     {
  1132.         if (graphType EQ CYLIND_GTYPE)
  1133.             SetCylindVectrs();
  1134.         else
  1135.             SetVectrs();
  1136.         pntsCurrent = FALSE;
  1137.     }
  1138.     if (hideSurface)
  1139.         if (scrnColor NEQ colorNorms)
  1140.             pntsCurrent = FALSE;
  1141.     if (NOT(pntsCurrent))
  1142.         SetPoints();
  1143.  
  1144.     CheckGrphWind();
  1145.     DrawGraph();
  1146.     PutGraphGrow();
  1147.     if (startRedraw NEQ -1)
  1148.         if ((Ticks - startRedraw) > 1800)
  1149.             SysBeep(1);
  1150.     startRedraw  = -1;
  1151.     DrawRotHndls();
  1152. }
  1153.  
  1154. PutGraphGrow()
  1155. {
  1156.     Rect    theRect;
  1157.  
  1158.     theRect = graphWind->portRect;
  1159.     theRect.left = theRect.right - SCBAR_WIDTH;
  1160.     theRect.top = theRect.bottom - SCBAR_WIDTH;
  1161.     ClipRect(&theRect);
  1162.     DrawGrowIcon(graphWind);
  1163.     ClipRect(&graphWind->portRect);
  1164. }
  1165.  
  1166. DrawGraph()
  1167. {
  1168. register    int    xCnt, yCnt;
  1169. register    Point    *grphPnts;
  1170.     Boolean        CmndPeriod();
  1171.  
  1172.     if (hideSurface)
  1173.     {
  1174.         DrawHiddenGraph();
  1175.         return;
  1176.     }
  1177.  
  1178.     EraseRect(&thePort->portRect);
  1179.     DrawAxes();
  1180.     if ((FrontWindow() EQ graphWind) AND NOT(scrnColor) AND grphOnScrn AND appActive)
  1181.     {
  1182.         HideCursor();
  1183.         grphPnts = graphPoints;
  1184.         xCnt = numX;
  1185.         while (xCnt--)
  1186.         {
  1187.             if (CmndPeriod())
  1188.             {
  1189.                 ShowCursor();
  1190.                 return;
  1191.             }
  1192.             MoveTo(*grphPnts++);
  1193.             yCnt = numY;
  1194.             while (--yCnt)
  1195.                 MLineTo(*grphPnts++);
  1196.         }
  1197.  
  1198.         for (yCnt = 0; yCnt < numY; yCnt++)
  1199.         {
  1200.             MoveTo(graphPoints[yCnt]);
  1201.             if (CmndPeriod())
  1202.             {
  1203.                 ShowCursor();
  1204.                 return;
  1205.             }
  1206.             grphPnts = graphPoints + (numY + yCnt);
  1207.             for (xCnt = 1; xCnt < numX; xCnt++)
  1208.             {
  1209.                 MLineTo(*grphPnts);
  1210.                 grphPnts += numY;
  1211.             }
  1212.         }
  1213.         ShowCursor();
  1214.     }
  1215.     else
  1216.     {
  1217.         grphPnts = graphPoints;
  1218.         xCnt = numX;
  1219.         while (xCnt--)
  1220.         {
  1221.             if (CmndPeriod())
  1222.                 return;
  1223.             MoveTo(*grphPnts++);
  1224.             yCnt = numY;
  1225.             while (--yCnt)
  1226.                 LineTo(*grphPnts++);
  1227.         }
  1228.         
  1229.         for (yCnt = 0; yCnt < numY; yCnt++)
  1230.         {
  1231.             MoveTo(graphPoints[yCnt]);
  1232.             if (CmndPeriod())
  1233.                 return;
  1234.             grphPnts = graphPoints + (numY + yCnt);
  1235.             for (xCnt = 1; xCnt < numX; xCnt++)
  1236.             {
  1237.                 LineTo(*grphPnts);
  1238.                 grphPnts += numY;
  1239.             }
  1240.         }
  1241.     }
  1242. }
  1243.  
  1244. static
  1245. DrawAxes()
  1246. {
  1247.     PenSize(2, 2);
  1248.     MoveTo(pass(Origin));
  1249.     LineTo(pass(XaxisPt));
  1250.     MoveTo(pass(Origin));
  1251.     LineTo(pass(YaxisPt));
  1252.     MoveTo(pass(Origin));
  1253.     LineTo(pass(ZaxisPt));
  1254.     PenSize(1, 1);
  1255. }
  1256.  
  1257. static
  1258. DrawHiddenGraph()
  1259. {
  1260.     PolyHandle    thePoly;
  1261.  
  1262.     if (xAxPos) {
  1263.         if (yAxPos)
  1264.             HideIt(0, 0, 1, 1, numX-1, numY-1);
  1265.         else
  1266.             HideIt(0, numY-2, 1, -1, numX-1, -1);
  1267.     }
  1268.     else {
  1269.         if (yAxPos)
  1270.             HideIt(numX-2, 0, -1, 1, -1, numY-1);
  1271.         else
  1272.             HideIt(numX-2, numY-2, -1, -1, -1, -1);
  1273.     }
  1274. }
  1275.  
  1276. static
  1277. HideIt(xStrt, yStrt, xStep, yStep, xEnd, yEnd)
  1278. int            xStrt, yStrt;
  1279. register    int    xStep, yStep;
  1280. int            xEnd, yEnd;
  1281. {
  1282. register    int    xCnt, yCnt;
  1283. register    long    offSet;
  1284.     PolyHandle     thePoly;
  1285.     Boolean        CmndPeriod();
  1286.  
  1287.     EraseRect(&thePort->portRect);
  1288.  
  1289.     for (xCnt = xStrt; xCnt NEQ xEnd; xCnt += xStep)
  1290.     {
  1291.         for (yCnt = yStrt; yCnt NEQ yEnd; yCnt += yStep)
  1292.         {
  1293.             thePoly = OpenPoly();
  1294.             offSet = (long)xCnt * numY + (long)yCnt;
  1295.             MoveTo(graphPoints[offSet]);
  1296.             LineTo(graphPoints[(long)xCnt * numY + (long)(yCnt+1)]);
  1297.             LineTo(graphPoints[(long)(xCnt+1) * numY + (long)(yCnt+1)]);
  1298.             LineTo(graphPoints[(long)(xCnt+1) * numY + (long)yCnt]);
  1299.             LineTo(graphPoints[offSet]);
  1300.             ClosePoly();
  1301.             SetGray(gridFace[offSet]);
  1302.             PaintPoly(thePoly);
  1303.             KillPoly(thePoly);
  1304.         }
  1305.         if (CmndPeriod())
  1306.             break;  /* for */
  1307.     }
  1308.     SetBlack();
  1309. }
  1310.  
  1311. static
  1312. SetBlack()
  1313. {
  1314.     RGBColor    theColor;
  1315.  
  1316.     if (scrnColor)
  1317.     {
  1318.         theColor.red = theColor.blue = theColor.green = 0;
  1319.         RGBForeColor(&theColor);
  1320.     }
  1321.     else
  1322.         PenPat(black);
  1323. }
  1324.  
  1325. static
  1326. FitRect(theRect, thePoint)
  1327. register    Rect    *theRect;
  1328. register    Point    *thePoint;
  1329. {
  1330.     if (thePoint->h < theRect->left)
  1331.         theRect->left = thePoint->h;
  1332.     else if (thePoint->h > theRect->right)
  1333.         theRect->right = thePoint->h;
  1334.  
  1335.     if (thePoint->v < theRect->top)
  1336.         theRect->top = thePoint->v;
  1337.     else if (thePoint->v > theRect->bottom)
  1338.         theRect->bottom = thePoint->v;
  1339. }
  1340.  
  1341.  
  1342. static
  1343. DoActivate()
  1344. {
  1345.     WindowPtr whichWindow;
  1346.  
  1347.     whichWindow = (WindowPtr) (theEvent.message);
  1348.     if (theEvent.modifiers & activeFlag)
  1349.     {
  1350.         ReadDeskScrap();
  1351.         SetPort(whichWindow);
  1352.     }
  1353.     else
  1354.         WriteDeskScrap();
  1355.  
  1356.     if (whichWindow EQ graphWind)
  1357.         PutGraphGrow();
  1358. }
  1359.  
  1360. static
  1361. DoSuspndRsm(message)
  1362. long    message;
  1363. {
  1364.     if (HIBYTE(message) NEQ 1)
  1365.         return;    /* not a suspend/resume */
  1366.  
  1367.     if (IS_SUSPND(message))
  1368.     {
  1369.         if (LOAD_CLIP(message))
  1370.             WriteDeskScrap();
  1371.         appActive = FALSE;
  1372.     }
  1373.     else    /* resume event */
  1374.     {
  1375.         if (LOAD_CLIP(message))    /* read back the clipboard? */
  1376.             ReadDeskScrap();
  1377.         appActive = TRUE;
  1378.     }
  1379. }
  1380.  
  1381. ShowFunctDial()
  1382. {
  1383.     if (functDOpen)
  1384.         SelectWindow(functDial);
  1385.     else
  1386.     {
  1387.         if (graphType EQ FUNCT_GTYPE)
  1388.             functDial = GetNewDialog(DIAL_FUNCT, &funcDialRecord, -1L);
  1389.         else if (graphType EQ CYLIND_GTYPE)
  1390.             functDial = GetNewDialog(DIAL_CYLIND, &funcDialRecord, -1L);
  1391.         else if (graphType EQ DERIV_GTYPE)
  1392.             functDial = GetNewDialog(DIAL_DERIV, &funcDialRecord, -1L);
  1393.         functDOpen = TRUE;
  1394.     }
  1395. }
  1396.  
  1397. ShowSpecs()
  1398. {
  1399.     if (specDOpen)
  1400.         SelectWindow(specDial);
  1401.     else {
  1402.         switch    (graphType) {
  1403.         case FUNCT_GTYPE:
  1404.             specDial = GetNewDialog(DIAL_SCALE_XY, &sdialRecord, -1L);
  1405.             specDOpen = TRUE;
  1406.             break;
  1407.         case CYLIND_GTYPE:
  1408.             specDial = GetNewDialog(DIAL_SCALE_RP, &sdialRecord, -1L);
  1409.             specDOpen = TRUE;
  1410.             break;
  1411.         case DERIV_GTYPE:
  1412.             specDial = GetNewDialog(DIAL_SCALE_XY, &sdialRecord, -1L);
  1413.             specDOpen = TRUE;
  1414.             break;
  1415.         case FDATA_GTYPE:
  1416.             break;
  1417.         }
  1418.     }
  1419. }
  1420.  
  1421. ShowLimits()
  1422. {
  1423.     if (limtDOpen)
  1424.         SelectWindow(limtDial);
  1425.     else {
  1426.         limtDial = GetNewDialog(DIAL_LIMT, &lmdialRecord, -1L);
  1427.         limtDOpen = TRUE;
  1428.     }
  1429. }
  1430.  
  1431. static
  1432. int
  1433. PZArcShow(theRect)
  1434. Rect    *theRect;
  1435. {
  1436.     Point    currMouseLoc;
  1437.     int        degrs, oldDegrs;
  1438.  
  1439.     GetMouse(&currMouseLoc);
  1440.     degrs = (180.0 / (Real)(theRect->right - theRect->left))
  1441.             * currMouseLoc.h;
  1442.     oldDegrs = degrs;
  1443.     InvertArc(theRect, 270 - degrs, degrs);
  1444.  
  1445.     while (Button())
  1446.     {
  1447.         GetMouse(&currMouseLoc);
  1448.         degrs = (180.0 / (Real)(theRect->right - theRect->left))
  1449.                 * currMouseLoc.h;
  1450.         if (degrs < 0)
  1451.             degrs = 0;
  1452.         else if (degrs > 180)
  1453.             degrs = 180;
  1454.         if (degrs NEQ oldDegrs)
  1455.         {
  1456.             InvertArc(theRect, 270 - degrs, degrs - oldDegrs);
  1457.             oldDegrs = degrs;
  1458.         }
  1459.     }
  1460.     InvertArc(theRect, 270 - degrs, degrs);
  1461.     return(degrs);
  1462. }
  1463.  
  1464. static
  1465. int
  1466. NZArcShow(theRect)
  1467. Rect    *theRect;
  1468. {
  1469.     Point    currMouseLoc;
  1470.     int        degrs, oldDegrs, widthRect;
  1471.  
  1472.     widthRect = theRect->right - theRect->left;
  1473.     GetMouse(&currMouseLoc);
  1474.     degrs = (180.0 / (Real)(widthRect))
  1475.             * (widthRect - currMouseLoc.h);
  1476.     oldDegrs = degrs;
  1477.     InvertArc(theRect, 90, degrs);
  1478.  
  1479.     while (Button())
  1480.     {
  1481.         GetMouse(&currMouseLoc);
  1482.         degrs = (180.0 / (Real)(widthRect))
  1483.                 * (widthRect - currMouseLoc.h);
  1484.         if (degrs < 0)
  1485.             degrs = 0;
  1486.         else if (degrs > 180)
  1487.             degrs = 180;
  1488.         if (degrs NEQ oldDegrs)
  1489.         {
  1490.             if (degrs < oldDegrs)
  1491.                 InvertArc(theRect, degrs + 90, oldDegrs - degrs);
  1492.             else
  1493.                 InvertArc(theRect, oldDegrs + 90, degrs - oldDegrs);
  1494.             oldDegrs = degrs;
  1495.         }
  1496.     }
  1497.  
  1498.     InvertArc(theRect, 90, degrs);
  1499.     return(degrs);
  1500. }
  1501.  
  1502.  
  1503. static
  1504. int
  1505. NYArcShow(theRect)
  1506. Rect    *theRect;
  1507. {
  1508.     Point    currMouseLoc;
  1509.     int        degrs, oldDegrs, heightRect;
  1510.  
  1511.     heightRect = theRect->bottom - theRect->top;
  1512.     GetMouse(&currMouseLoc);
  1513.     degrs = (180.0 / (Real)(heightRect))
  1514.             * currMouseLoc.v;
  1515.     oldDegrs = degrs;
  1516.     InvertArc(theRect, 0, degrs);
  1517.  
  1518.     while (Button())
  1519.     {
  1520.         GetMouse(&currMouseLoc);
  1521.         degrs = (180.0 / (Real)(heightRect))
  1522.                 * currMouseLoc.v;
  1523.         if (degrs < 0)
  1524.             degrs = 0;
  1525.         else if (degrs > 180)
  1526.             degrs = 180;
  1527.         if (degrs NEQ oldDegrs)
  1528.         {
  1529.             if (degrs < oldDegrs)
  1530.                 InvertArc(theRect, degrs, oldDegrs - degrs);
  1531.             else
  1532.                 InvertArc(theRect, oldDegrs, degrs - oldDegrs);
  1533.             oldDegrs = degrs;
  1534.         }
  1535.     }
  1536.     InvertArc(theRect, 0, degrs);
  1537.  
  1538.     return(degrs);
  1539. }
  1540.  
  1541. static
  1542. int
  1543. PYArcShow(theRect)
  1544. Rect    *theRect;
  1545. {
  1546.     Point    currMouseLoc;
  1547.     int        degrs, oldDegrs, heightRect;
  1548.  
  1549.     heightRect = theRect->bottom - theRect->top;
  1550.     GetMouse(&currMouseLoc);
  1551.     degrs = (180.0 / (Real)(heightRect))
  1552.             * (heightRect - currMouseLoc.v);
  1553.     oldDegrs = degrs;
  1554.     InvertArc(theRect, 180 - degrs, degrs);
  1555.  
  1556.     while (Button())
  1557.     {
  1558.         GetMouse(&currMouseLoc);
  1559.         degrs = (180.0 / (Real)(heightRect))
  1560.                 * (heightRect - currMouseLoc.v);
  1561.         if (degrs < 0)
  1562.             degrs = 0;
  1563.         else if (degrs > 180)
  1564.             degrs = 180;
  1565.         if (degrs NEQ oldDegrs)
  1566.         {
  1567.             if (degrs < oldDegrs)
  1568.                 InvertArc(theRect, 180 - oldDegrs, oldDegrs - degrs);
  1569.             else
  1570.                 InvertArc(theRect, 180 - degrs, degrs - oldDegrs);
  1571.             oldDegrs = degrs;
  1572.         }
  1573.     }
  1574.     InvertArc(theRect, 180 - degrs, degrs);
  1575.  
  1576.     return(degrs);
  1577. }
  1578.  
  1579. static
  1580. int
  1581. XArcShow(theRect)
  1582. Rect    *theRect;
  1583. {
  1584.     int        degrs, oldDegrs;
  1585.     double    angle, MouseAngle();
  1586.     Point    currMsPos, oldMsPos, presPos, oldPos;
  1587.     int        startAngle, oldAngle, presAngle, rotAngle;
  1588.  
  1589.     PenMode(patXor);
  1590.     PenSize(2, 2);
  1591.     GetMouse(&oldMsPos);
  1592.     oldPos = drawWCntr;
  1593.  
  1594.     do
  1595.     {
  1596.         GetMouse(&currMsPos);
  1597.         if ((currMsPos.h NEQ oldMsPos.h) OR (currMsPos.v NEQ oldMsPos.v))
  1598.         {
  1599.             angle = MouseAngle(currMsPos);
  1600.             presPos.h = (int)(drawWCntr.v * sin(angle)) + drawWCntr.h;
  1601.             presPos.v = -(int)(drawWCntr.v * cos(angle)) + drawWCntr.v;
  1602.             angle = MouseAngle(currMsPos);
  1603.             presPos.h = (int)(drawWCntr.v * sin(angle)) + drawWCntr.h;
  1604.             presPos.v = -(int)(drawWCntr.v * cos(angle)) + drawWCntr.v;
  1605.             ReDrwLine(drawWCntr.v, drawWCntr.h, presPos, oldPos);
  1606.             oldPos = presPos;
  1607.             oldMsPos = currMsPos;
  1608.         }
  1609.     } while (Button());
  1610.     startAngle = round(angle * RADtoDEG);
  1611.  
  1612.     oldAngle = startAngle;
  1613.     do
  1614.     {
  1615.         GetMouse(&currMsPos);
  1616.         if ((currMsPos.h NEQ oldMsPos.h) OR (currMsPos.v NEQ oldMsPos.v))
  1617.         {
  1618.             angle = MouseAngle(currMsPos) * RADtoDEG;
  1619.             presAngle = round(angle);
  1620.             rotAngle = RelativAngle(startAngle, presAngle);
  1621.  
  1622.             InvertArc(theRect, startAngle + RelativAngle(startAngle, oldAngle),
  1623.                     RelativAngle(startAngle, presAngle)
  1624.                     - RelativAngle(startAngle, oldAngle));
  1625.  
  1626.             oldAngle = presAngle;
  1627.             oldMsPos = currMsPos;
  1628.         }
  1629.     } while (NOT(Button()));
  1630.  
  1631.     if (presAngle - startAngle > 0)
  1632.         return(presAngle - startAngle);
  1633.     else
  1634.         return(360 + presAngle - startAngle);
  1635.     PenMode(patCopy);
  1636.     PenSize(1, 1);
  1637. }
  1638.  
  1639. /*** Update the position of a line ***/
  1640. ReDrwLine(strt, presPos, oldPos)
  1641. Point        strt, presPos, oldPos;
  1642. {
  1643.     MoveTo(strt);
  1644.     LineTo(oldPos);
  1645.     MoveTo(strt);
  1646.     LineTo(presPos);
  1647. }
  1648.  
  1649.  
  1650. double
  1651. MouseAngle(currMsLoc)
  1652. Point    currMsLoc;
  1653. {
  1654.     Point    msCntrLoc;
  1655.     double    angle;
  1656.  
  1657.     msCntrLoc.h = currMsLoc.h - drawWCntr.h;
  1658.     msCntrLoc.v = currMsLoc.v - drawWCntr.v;
  1659.     angle = atan((double)msCntrLoc.h / msCntrLoc.v);
  1660.     angle = Abs(angle);
  1661.  
  1662.     if (msCntrLoc.h > 0)
  1663.         if (msCntrLoc.v > 0)
  1664.             angle = PI - angle;
  1665.         else
  1666.         {}
  1667.     else
  1668.     {
  1669.         if (msCntrLoc.v > 0)
  1670.             angle -= PI;
  1671.         else
  1672.             angle = -angle;
  1673.     }
  1674.  
  1675.     return(angle);
  1676. }
  1677.  
  1678.  
  1679. int
  1680. RelativAngle(startAngle, presAngle)
  1681. int    startAngle, presAngle;
  1682. {
  1683.     int    relAngle;
  1684.  
  1685.     if (presAngle - startAngle > 0)
  1686.         relAngle = (presAngle - startAngle);
  1687.     else
  1688.         relAngle = (360 + presAngle - startAngle);
  1689.     if (relAngle > 180)
  1690.         relAngle -= 360;
  1691.     return(relAngle);
  1692. }
  1693.  
  1694. My_printf(shwStr)
  1695. char    *shwStr;
  1696. {
  1697.     char    pbuffer[256];
  1698.     GrafPtr    savePort;
  1699. static    Rect    dispRect = {21, 320, 40, 510};
  1700.     
  1701.     GetPort(&savePort);
  1702.     SetPort(windManPort);
  1703.         ClipRect(&dispRect);
  1704.         EraseRect(&dispRect);
  1705.         MoveTo(330, 36);
  1706.         strcpy(pbuffer, shwStr);
  1707.         ctop(pbuffer);
  1708.         DrawString(pbuffer);
  1709.     SetPort(savePort);
  1710. }
  1711.  
  1712. Wait()
  1713. {
  1714.     EventRecord    msEvent;
  1715.     
  1716.     while(!Button());
  1717.     while(Button());
  1718.     GetNextEvent(mDownMask, &msEvent);
  1719. }
  1720.  
  1721. static    GrafPtr    _oldPort;
  1722.  
  1723. SavePort()
  1724. {
  1725.     GetPort(&_oldPort);
  1726. }
  1727.  
  1728. RestorePort()
  1729. {
  1730.     SetPort(_oldPort);
  1731. }
  1732.  
  1733.  
  1734. static    DialogPtr        meterDlg;
  1735. static    Real    meterAngle, lstDrwnAngle, meterDelta;
  1736. static    Rect    meterRect = { 10, 10, 93, 93 };
  1737.  
  1738. ShowMeter(elements)
  1739. long    elements;
  1740. {
  1741. static    DialogRecord    meterRecord;    /* storage for the dialog */
  1742.  
  1743.     if (inMultiFndr)
  1744.     {
  1745.         SavePort();
  1746.         SelectWindow(graphWind);
  1747.         SetPort(graphWind);
  1748.         EraseRect(&meterRect);
  1749.         FrameOval(&meterRect);
  1750.         RestorePort();
  1751.     }
  1752.     else
  1753.     {
  1754.         meterDlg = GetNewDialog(DIAL_METER, &meterRecord, -1L);
  1755.         DrawDialog(meterDlg);
  1756.         SavePort();
  1757.         SetPort(meterDlg);
  1758.         FrameOval(&meterRect);
  1759.     }
  1760.  
  1761.     meterDelta = 360.0 / elements;
  1762.     meterAngle = lstDrwnAngle = 0.0;
  1763. }
  1764.  
  1765. DisplayMeter()
  1766. {
  1767.     GrafPtr    svPort;
  1768.  
  1769.     meterAngle += meterDelta;
  1770.     if (meterAngle > (lstDrwnAngle + 3))
  1771.     {
  1772.         lstDrwnAngle = meterAngle;
  1773.         if (inMultiFndr)
  1774.         {
  1775.             GetPort(&svPort);
  1776.             SetPort(graphWind);
  1777.             FillArc(&meterRect, 0, (int)meterAngle, black);
  1778.             SetPort(svPort);
  1779.         }
  1780.         else
  1781.             FillArc(&meterRect, 0, (int)meterAngle, black);
  1782.     }
  1783. }
  1784.  
  1785. RemoveMeter()
  1786. {
  1787.     register    int    i = 4;
  1788.  
  1789.     if (NOT(inMultiFndr))
  1790.     {
  1791.         CloseDialog(meterDlg);
  1792.     
  1793.         noRedrawGrph = TRUE;
  1794.         RestorePort();
  1795.         while (i--)
  1796.             if (GetNextEvent(updateMask, &theEvent))
  1797.                 DoEvent();
  1798.         noRedrawGrph = FALSE;
  1799.     }
  1800. }
  1801.  
  1802.  
  1803.  
  1804. /***  read in deskscrap (clipboard)  ***/
  1805. ReadDeskScrap()
  1806. {
  1807.     long    scrapLen, scrapOffset;
  1808.  
  1809.     if (scrapCompare NEQ ScrapInfo.scrapCount)
  1810.     {
  1811.         scrapLen = GetScrap(NIL, 'TEXT', &scrapOffset);
  1812.         if (scrapLen >= 0)
  1813.             if (TEFromScrap() < 0)    /* ROM */
  1814.                 scrapLen = 0;    /* was an error */
  1815.         if (NOT(scrapLen))
  1816.         {
  1817.             TESetScrapLen(0);    /* ROM */
  1818.             isScrapTE = FALSE;
  1819.         }
  1820.         else
  1821.             isScrapTE = TRUE;
  1822.  
  1823.         scrapCompare = ScrapInfo.scrapCount;
  1824.     }
  1825.     SetEditMenu();
  1826. }
  1827.  
  1828. /***  write out deskscrap (clipboard)  ***/
  1829. WriteDeskScrap()
  1830. {
  1831.     if (scrapDirty AND isScrapTE)
  1832.     {
  1833.         scrapCompare = ZeroScrap();
  1834.         TEToScrap();    /* ROM */
  1835.         scrapDirty = FALSE;
  1836.     }
  1837.     SetEditMenu();
  1838. }
  1839.  
  1840.  
  1841. /***  enable or gray out approriate items in the menu  ***/
  1842. SetEditMenu()
  1843. {
  1844.     WindowPtr frontW;
  1845.     Boolean        IsDialog(), IsList();
  1846.  
  1847.     frontW = FrontWindow();
  1848.     if (frontW EQ graphWind)
  1849.     {
  1850.         DisableItem(editMenu, EDIT_UNDO);    /* ROM */
  1851.         DisableItem(editMenu, EDIT_CUT);
  1852.         EnableItem(editMenu, EDIT_COPY);
  1853.         DisableItem(editMenu, EDIT_PASTE);
  1854.         DisableItem(editMenu, EDIT_CLEAR);
  1855.     }
  1856.     else if (IsDialog(frontW))
  1857.     {
  1858.         DisableItem(editMenu, EDIT_UNDO);    /* ROM */
  1859.         EnableItem(editMenu, EDIT_CUT);
  1860.         EnableItem(editMenu, EDIT_COPY);
  1861.         if (isScrapTE)
  1862.             EnableItem(editMenu, EDIT_PASTE);
  1863.         else
  1864.             DisableItem(editMenu, EDIT_PASTE);
  1865.         EnableItem(editMenu, EDIT_CLEAR);
  1866.     }
  1867.     else    /* menu for DA */
  1868.     {
  1869.         EnableItem(editMenu, EDIT_UNDO);
  1870.         EnableItem(editMenu, EDIT_CUT);
  1871.         EnableItem(editMenu, EDIT_COPY);
  1872.         EnableItem(editMenu, EDIT_PASTE);
  1873.         EnableItem(editMenu, EDIT_CLEAR);
  1874.     }
  1875. }
  1876.  
  1877. #define    KEYMAP    ((long *)0x174)
  1878.  
  1879. int
  1880. ShiftDown()
  1881. {
  1882.     return(KEYMAP[1] & 1);
  1883. }
  1884.  
  1885. int
  1886. OptionDown()
  1887. {
  1888.     return(KEYMAP[1] & 4);
  1889. }
  1890.  
  1891. int
  1892. CapsDown()
  1893. {
  1894.     return(KEYMAP[1] & 2);
  1895. }
  1896.  
  1897.  
  1898. pascal void
  1899. RMoveTo(a)
  1900. long    a;
  1901. {
  1902.     asm{
  1903.         move.l  a,-(a7)
  1904.         move.l  MoveToAddr,a0
  1905.         jsr     (a0)
  1906.     }
  1907. }
  1908.  
  1909. pascal void
  1910. RLineTo(a)
  1911. long    a;
  1912. {
  1913.     asm{
  1914.         move.l  a,-(a7)
  1915.         move.l  LineToAddr,a0
  1916.         jsr     (a0)
  1917.     }
  1918. }
  1919.  
  1920. Clock()
  1921. {
  1922.     CursHandle        theCursH;
  1923.  
  1924.     theCursH = GetCursor(4);
  1925.     SetCursor(*theCursH);
  1926. }
  1927.  
  1928. GenralAlert(mesg)
  1929. char    *mesg;
  1930. {
  1931.     ParamText(mesg, "", "", "");
  1932.     InitCursor();
  1933.     Alert(ALERT_GENRAL, NIL);
  1934. }
  1935.  
  1936.  
  1937.  
  1938. /*********************************************/
  1939. /*****    MultiFinder "multitasking" stuff *****/
  1940.  
  1941.  
  1942. Boolean
  1943. CmndPeriod()
  1944. {
  1945.     int        evntMask;
  1946.     EventRecord    keyEvent;
  1947.     Boolean        CmndEvent();
  1948. static    long    lastTm = 0xf0000000;
  1949.  
  1950.     if (appActive)
  1951.         if ((Ticks - lastTm) < 5)
  1952.             return(FALSE);
  1953.     lastTm = Ticks;
  1954.  
  1955.     if (inMultiFndr)
  1956.     {
  1957.         evntMask = everyEvent - updateMask;
  1958.         if (WaitNextEvent(evntMask, &keyEvent, sleepPeriod, NIL))
  1959.         {
  1960.             if (keyEvent.what EQ resumEvt)
  1961.                 DoSuspndRsm(keyEvent.message);
  1962.             else if (CmndEvent(&keyEvent))
  1963.                 return(TRUE);
  1964.         }
  1965.     }
  1966.     else
  1967.     {
  1968.         SystemTask();
  1969.         if (EventAvail(keyDownMask, &keyEvent))
  1970.             if (CmndEvent(&keyEvent))
  1971.                 return(TRUE);
  1972.     }
  1973.     return(FALSE);    
  1974. }
  1975.  
  1976. static
  1977. Boolean
  1978. CmndEvent(chkEvent)
  1979. EventRecord        *chkEvent;
  1980. {
  1981.     if (chkEvent->what EQ keyDown)
  1982.         if ((chkEvent->message & charCodeMask) EQ '.')
  1983.             if (chkEvent->modifiers & cmdKey)
  1984.                 return(TRUE);
  1985.     return(FALSE);
  1986. }
  1987.  
  1988.  
  1989.  
  1990.  
  1991.  
  1992.  
  1993. SetRotateHandles()
  1994. {
  1995.     int        halfWid, width;
  1996.     Rect    drawRect;
  1997.  
  1998.     drawRect = graphWind->portRect;
  1999.     drawWCntr.h = DIV_2(drawRect.right - drawRect.left) + drawRect.left;
  2000.     drawWCntr.v = DIV_2(drawRect.bottom - drawRect.top) + drawRect.top;
  2001.  
  2002.     hndRct[0].top = drawRect.top - 1;
  2003.     hndRct[0].left = drawWCntr.h - 7;
  2004.     hndRct[0].bottom = hndRct[0].top + 13;
  2005.     hndRct[0].right = drawWCntr.h + 7;
  2006.  
  2007.     hndRct[1].top = drawRect.bottom - 12;
  2008.     hndRct[1].left = hndRct[0].left;
  2009.     hndRct[1].bottom = drawRect.bottom + 1;
  2010.     hndRct[1].right = hndRct[0].right;
  2011.  
  2012.     hndRct[2].top = drawWCntr.v - 7;
  2013.     hndRct[2].bottom = drawWCntr.v + 7;
  2014.     hndRct[2].left = -1;
  2015.     hndRct[2].right = 12;
  2016.  
  2017.     hndRct[3].top = hndRct[2].top;
  2018.     hndRct[3].left = drawRect.right - 12;
  2019.     hndRct[3].bottom = hndRct[2].bottom;
  2020.     hndRct[3].right = drawRect.right + 1;
  2021.  
  2022.     hndRct[4].top = drawRect.top - 1;
  2023.     hndRct[4].bottom = hndRct[4].top + 13;
  2024.     hndRct[4].left = -1;
  2025.     hndRct[4].right = 12;
  2026.  
  2027.     width = (MIN(drawWCntr.h, drawWCntr.v) * 100) / 152;
  2028.     halfWid = width / 2;
  2029.  
  2030.     vertRect.top = drawRect.top;
  2031.     vertRect.left = drawWCntr.h - halfWid;
  2032.     vertRect.bottom = drawRect.bottom;
  2033.     vertRect.right = drawWCntr.h + halfWid;
  2034.  
  2035.     horizRect.top = drawWCntr.v - halfWid;
  2036.     horizRect.left = 0;
  2037.     horizRect.bottom = drawWCntr.v + halfWid;
  2038.     horizRect.right = drawRect.right;
  2039.  
  2040.     centrRect.top = drawWCntr.v - width;
  2041.     centrRect.left = drawWCntr.h - width;
  2042.     centrRect.bottom = drawWCntr.v + width;
  2043.     centrRect.right = drawWCntr.h + width;
  2044. }
  2045.  
  2046. DrawRotHndls()
  2047. {
  2048.     int        i;
  2049.  
  2050.     PenMode(patXor);
  2051.     for (i = 0; i < 5; i++)
  2052.         FrameRect(hndRct + i);
  2053.     PenMode(patCopy);
  2054. }
  2055.  
  2056. int
  2057. WhatQuad(pntPtr)
  2058. Point    *pntPtr;
  2059. {
  2060.     int        i;
  2061.  
  2062.     for (i = 0; i < 5; i++)
  2063.         if (PtInRect(*pntPtr, hndRct + i))
  2064.             return(i);
  2065.     return(-1);
  2066. }
  2067.